﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace nr.Tombola.Cards
{
    [Serializable()]
    public class CardRow : System.Runtime.Serialization.ISerializable
    {
        private int[] Numbers { get; set; }

        public CardRow(SerializationInfo info, StreamingContext context)
        {
            Numbers = (int[])info.GetValue("numbers", typeof(int[]));
        }

        public CardRow(params int[] numbers)
        {
            if (numbers.Length > 5)
                numbers = numbers.Take(5).ToArray();
            Array.Sort(numbers);
            Numbers = new int[9];
            foreach (int number in numbers) Place(number);
        }

        public int this[int index]
        {
            get
            {
                if ((index < 0) || (index > 8))
                    throw new ArgumentOutOfRangeException("index", index, "The index must value by 0 and 8.");
                return Numbers[index];
            }
        }

        public int Count
        {
            get
            {
                int count = 0;
                for (int index = 0; index < 9; ++index) if (Numbers[index] != 0) ++count;
                return count;
            }
        }

        public int[] GetNumbers()
        {
            return (from int n in Numbers where n > 0 select n).ToArray();
        }

        public void Replace(int oldNumber, int newNumber)
        {
            int oldDec = Card.GetDec(oldNumber);
            int newDec = Card.GetDec(newNumber);
            if ((Numbers[oldDec] != 0) && (Numbers[newDec] == 0))
            {
                Numbers[oldDec] = 0;
                Numbers[newDec] = newNumber;
            }
            else
                throw new ArgumentException("Unable to replace, because the place of old number is empty or the place of new number is not empty.");
        }

        public void Clear(int index)
        {
            if ((index < 0) || (index > 8))
                throw new ArgumentOutOfRangeException("index", index, "The index must value by 0 and 8.");

            Numbers[index] = 0;
        }

        public bool Place(int number)
        {
            return Place(number, false);
        }

        public bool Place(int number, bool subst)
        {
            if ((number < 1) || (number > 90))
                throw new ArgumentOutOfRangeException("number", number, "The number must value by 1 and 90.");
            bool result = (Count < 5) || subst;
            if (result)
            {
                int dec = Card.GetDec(number);

                if (Numbers[dec] == 0)
                    Numbers[dec] = number;
                else
                    if (subst)
                        Numbers[dec] = number;
                    else
                        result = false;
            }
            return result;
        }

        public bool Contains(int number)
        {
            if (number == 0) return false;

            return Numbers.Contains(number);
        }

        #region ISerializable Members

        public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
        {
            info.AddValue("numbers", Numbers);
        }

        #endregion
    }
}
